package com.example.demo.index;

import lombok.Data;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Data
public class TestService implements InitializingBean {

    @Value("${Schedules.User_Agent}")
    private String User_Agent;

    @Value("${Schedules.CORONA_VIRUS_CONFIRMED_DATA_URL}")
    private String CORONA_VIRUS_CONFIRMED_DATA_URL;

    @Value("${Schedules.CORONA_VIRUS_RECOVERED_DATA_URL}")
    private String CORONA_VIRUS_RECOVERED_DATA_URL;

    @Value("${Schedules.CORONA_VIRUS_DEATHS_DATA_URL}")
    private String CORONA_VIRUS_DEATHS_DATA_URL;

    private TotalNum confirmed = new TotalNum();

    private TotalNum recovered = new TotalNum();

    private TotalNum deaths = new TotalNum();

    private TotalNum nowConfirm = new TotalNum();


    public List<CSVRecord> getCSVRecordsByURL(String url) throws IOException {
        RequestEntity<Void> requestEntity = RequestEntity
                .get(URI.create(url))
                .headers(httpHeaders -> httpHeaders.add("User-Agent", User_Agent))
                .build();
        ResponseEntity<Resource> exchange = new RestTemplate().exchange(requestEntity, Resource.class);
        assert exchange.getBody() != null;
        Reader in = new InputStreamReader(exchange.getBody().getInputStream());
        CSVFormat csvFileFormat = CSVFormat.DEFAULT.withHeader();
        CSVParser csvFileParser = new CSVParser(in, csvFileFormat);
        return csvFileParser.getRecords();
    }

    @Scheduled(cron = "${Schedules.updateVirusDataCron}")
    public void fetchAllConfirmedRecords() throws IOException {
        List<CSVRecord> csvRecords = getCSVRecordsByURL(CORONA_VIRUS_CONFIRMED_DATA_URL);
        csvRecords.forEach(record -> {
                    int latestTotalCases = Integer.parseInt(record.get(record.size() - 1));
                    int pre = Integer.parseInt(record.get(record.size() - 2));
                    int diffFromPrevDay = latestTotalCases - pre;
                    confirmed.totalCases += latestTotalCases;
                    confirmed.diffFromPrevDay += diffFromPrevDay;
                });
    }

    @Scheduled(cron = "${Schedules.updateVirusDataCron}")
    public void fetchAllRecoveredRecords() throws IOException {
        List<CSVRecord> csvRecords = getCSVRecordsByURL(CORONA_VIRUS_RECOVERED_DATA_URL);
        csvRecords.forEach(record -> {
            int latestTotalCases = Integer.parseInt(record.get(record.size() - 1));
            int pre = Integer.parseInt(record.get(record.size() - 2));
            int diffFromPrevDay = latestTotalCases - pre;
            recovered.totalCases += latestTotalCases;
            recovered.diffFromPrevDay += diffFromPrevDay;
        });
    }

    @Scheduled(cron = "${Schedules.updateVirusDataCron}")
    public void fetchAllDeathsRecords() throws IOException {
        List<CSVRecord> csvRecords = getCSVRecordsByURL(CORONA_VIRUS_DEATHS_DATA_URL);
        csvRecords.forEach(record -> {
            int latestTotalCases = Integer.parseInt(record.get(record.size() - 1));
            int pre = Integer.parseInt(record.get(record.size() - 2));
            int diffFromPrevDay = latestTotalCases - pre;
            deaths.totalCases += latestTotalCases;
            deaths.diffFromPrevDay += diffFromPrevDay;
        });
    }

    /**
     * 初始化bean的时候，如果bean实现了InitializingBean接口，会自动调用afterPropertiesSet方法
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        fetchAllConfirmedRecords();
        fetchAllRecoveredRecords();
        fetchAllDeathsRecords();
        nowConfirm.totalCases = confirmed.totalCases - recovered.totalCases - deaths.totalCases;
        nowConfirm.diffFromPrevDay = confirmed.diffFromPrevDay - recovered.diffFromPrevDay - deaths.diffFromPrevDay;
    }

}
